﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using lumo.input;
using Microsoft.Xna.Framework;
using lumo.display.object2D;
using FarseerPhysics.Dynamics;

namespace game
{
    /// <summary>
    /// Global Static class.
    /// </summary>
    public static class Global
    {
        // Constants
        public const float   TimeStep       = 1.0f / 30.0f;
        public const int     AditionalTiles = 4;
        public static readonly Vector2 DefaultScreenSize = new Vector2(1024.0f, 768.0f);
        public static readonly Vector2 ScreenSize = new Vector2(1024, 768);

        public static game.display.Camera Camera = new game.display.Camera();
        public static game.character.GameMap Map;

        // Variables
        public static Keypad     Keypad = null;
        public static Joystick   Joystick = null;
        public static Cursor     Cursor = null;
        public static Sprite     CursorSprite = null;
        public static Random     Random = new Random();
        public static BoxOverlay Box = null;

        // Physics Variablles.
        public static float      Accum = 0;
        public const float       PhysicsScale = 100.0f;
        public const float       StepTime     = 1.0f / 60.0f;

        public static Matrix ScreenMatrix { get { return Matrix.CreateScale(ScreenSize.X / DefaultScreenSize.X, ScreenSize.Y / DefaultScreenSize.Y, 1.0f); } }

        /// <summary>
        /// Physics category
        /// </summary>
        public static class PhysicsCategory
        {
            public const Category Level = Category.Cat1;
            public const Category Actor = Category.Cat2;
            public const Category ActorBullet = Category.Cat3;
            public const Category Enemy = Category.Cat4;
            public const Category EnemyBullet = Category.Cat5;
            public const Category Sensor = Category.Cat6;
            public const Category All = Category.All;

            public static Category AllBut(Category Cat) { return (Category.All & (~Cat)); }
        };

        /// <summary>
        /// Controller
        /// </summary>
        public static class Controller
        {
            public static ThumbstickWrapper MovementThumbstick;

            /// <summary>Initialize the controller globals. </summary>
            public static void Initialize(lumo.LumoComponent Game)
            {
                MovementThumbstick = new ThumbstickWrapper();
                MovementThumbstick.Add(Thumbstick.FromKeypadWASD(Global.Keypad));
                MovementThumbstick.Add(Thumbstick.FromKeypadArrows(Global.Keypad));
                MovementThumbstick.Add(new Thumbstick(Joystick.GetAxis(lumo.input.Joystick.Axis.X), Joystick.GetAxis(lumo.input.Joystick.Axis.Y)));
            }

            /// <summary>Initialize the controller globals. </summary>
            public static void Update(lumo.LumoComponent Game)
            {
                MovementThumbstick.Update(Game);
            }
        };

        /// <summary>
        /// Initialize the globals.
        /// </summary>
        /// <param name="Game"></param>
        public static void Initialize(lumo.LumoComponent Game)
        {
            Keypad       = new Keypad();
            Cursor       = new Cursor();
            Joystick     = new Joystick(0);
            CursorSprite = new Sprite();
            Box          = new BoxOverlay(Game, DefaultScreenSize.X, DefaultScreenSize.Y);
            Map          = new character.GameMap(Game);
            // Controller
            Controller.Initialize(Game);
        }

        /// <summary>
        /// Update the Globals.
        /// </summary>
        /// <param name="Game"></param>
        public static void Update(lumo.LumoComponent Game)
        {
            Keypad.Update(Game);
            Cursor.Update(Game);
            Controller.Update(Game);
            CursorSprite.Position = new Vector2(Cursor.X, Cursor.Y);
            Accum += (float) Game.GameTime.ElapsedGameTime.TotalSeconds;
            while (Accum >= StepTime)
            {
                if (Map.World != null)
                    Map.World.Step(StepTime);
                Accum -= StepTime;
            }
        }
    }
}
